package unimelb.distSystems.project2;

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.security.MessageDigest;

import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;

/*
 * Subclass of GUIScreen for registering a new account for the game
 */
public class CreateAccountScreen extends GUIScreen {
	/*
	 * GUI components
	 */
	private JButton create_button = new JButton("Create a new account");
	private JButton cancel_button = new JButton("Cancel");
	private JButton browse_button = new JButton("Browse");
	private JLabel username_text = new JLabel("Username");
	private JLabel password_text = new JLabel("Password");
	private JLabel drivername_text = new JLabel("Driver name (Other players can see)");
	private JLabel avatar_text = new JLabel("Avatar");
	private JTextField username_tf = new JTextField(30);
	private JTextField password_tf = new JTextField(30);
	private JTextField drivername_tf = new JTextField(30);
	private JTextField avatar_field = new JTextField(30);
	private JFileChooser avatar_chooser = new JFileChooser();
	private JLabel title_text = new JLabel("Register a new account for the game");

	/*
	 * Constructor
	 */
	public CreateAccountScreen(Game client) {
		super();
		initialise_listeners(client);
		title_text.setFont(new Font(null,Font.BOLD,30));
		avatar_field.setEditable(false);
		avatar_field.setBackground(Color.WHITE);
		
		username_tf.setPreferredSize(new Dimension(260,30));
		password_tf.setPreferredSize(new Dimension(260,30));
		drivername_tf.setPreferredSize(new Dimension(260,30));
		avatar_field.setPreferredSize(new Dimension(260,30));
	}
	
	/*
	 * @see unimelb.distSystems.project2.GUIScreen#perform_actions_prior_dislay()
	 */
	public void perform_actions_prior_display() {
		//Make sure all components do not hold any previous data
		username_tf.setText("");
		password_tf.setText("");
		drivername_tf.setText("");
		avatar_field.setText("");
		
		avatar_chooser.setSelectedFile(new File(""));
	}
	
	/*
	 * @see unimelb.distSystems.project2.GUIScreen#perform_actions_prior_exit()
	 */
	public void perform_actions_prior_exit() {
		//Nothing
	}

	/*
	 * @see unimelb.distSystems.project2.GUIScreen#display(java.awt.Container)
	 */
	public void display(Container screen_container) {
		GridBagConstraints c = new GridBagConstraints();
		c.fill = GridBagConstraints.HORIZONTAL;
		screen_container.setLayout(new FlowLayout());
		
		JPanel title_p = new JPanel();
		title_p.setLayout(new GridBagLayout());
		title_p.add(title_text);
		screen_container.add(title_p);
		
		JPanel main_p = new JPanel();
		main_p.setLayout(new GridBagLayout());
		screen_container.add(main_p);
		
		c.gridx = 0;
		c.gridy = 0;
		main_p.add(username_text,c);
		
		c.gridx = 0;
		c.gridy = 1;
		c.gridwidth = 2;
		main_p.add(username_tf,c);
		c.gridwidth = 1;
		
		c.gridx = 0;
		c.gridy = 2;
		main_p.add(blank,c);
		
		c.gridx = 0;
		c.gridy = 3;
		main_p.add(password_text,c);
		
		c.gridx = 0;
		c.gridy = 4;
		c.gridwidth = 2;
		main_p.add(password_tf,c);
		c.gridwidth = 1;
		
		c.gridx = 0;
		c.gridy = 5;
		main_p.add(blank2,c);
		
		c.gridx = 0;
		c.gridy = 6;
		main_p.add(drivername_text,c);
		
		c.gridx = 0;
		c.gridy = 7;
		c.gridwidth = 2;
		main_p.add(drivername_tf,c);
		c.gridwidth = 1;
		
		c.gridx = 0;
		c.gridy = 8;
		main_p.add(blank3,c);
		
		c.gridx = 0;
		c.gridy = 9;
		main_p.add(avatar_text,c);
		
		c.gridx = 0;
		c.gridy = 10;
		c.gridwidth = 2;
		main_p.add(avatar_field,c);
		c.gridwidth = 1;
		
		c.gridx = 1;
		c.gridy = 11;
		main_p.add(browse_button,c);
		
		c.gridx = 0;
		c.gridy = 12;
		main_p.add(blank4,c);
		
		c.gridx = 0;
		c.gridy = 13;
		main_p.add(create_button,c);
		
		c.gridx = 1;
		c.gridy = 13;
		main_p.add(cancel_button,c);
	}

	/*
	 * @see unimelb.distSystems.project2.GUIScreen#initialise_listeners(unimelb.distSystems.project2.Game)
	 */
	protected void initialise_listeners(final Game client) {
		/*
		 * Selecting custom picture for avatar
		 */
		browse_button.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				avatar_chooser.showOpenDialog(client);
				if(avatar_chooser.getSelectedFile()==null)
					return;

				validate_avatar(avatar_chooser.getSelectedFile().getName());
			}
		});
		
		/*
		 * Leave the screen
		 */
		cancel_button.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				client.go_to_screen(Game.LOGIN_SCREEN);
			}
		});
		
		/*
		 * Create and pass new Player instance to server
		 */
		create_button.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				if(valid_all())
				{
					Player new_player=create_new_account();
					if(new_player==null)
						return;
					
					////////////////////////////////////
					//COBRA COMMUNICATION
					////////////////////////////////////
					//Return the new player object to GameServer
					boolean success=true;
					
					if(success)
					{
						JOptionPane.showMessageDialog(null,"Your account is successfully created.",
								"Success",JOptionPane.INFORMATION_MESSAGE);
						client.go_to_screen(Game.LOGIN_SCREEN);
					}
				}
			}
		});
	}

	/*
	 * Check that the custom picture is within allowable limits
	 * Input: String filename to the picture
	 * Output: Nothing
	 */
	private void validate_avatar(String filename)
	{
		String[] ss = filename.split("\\.");
		if(ss.length>1)
		{
			String extension = ss[1];
			if(Configurations.allowable_extensions.indexOf(extension)>=0)
				avatar_field.setText(avatar_chooser.getSelectedFile().getAbsolutePath());
			else
			{
				JOptionPane.showMessageDialog(null,"Type of the selected picture is not allowed.",
						"Error",JOptionPane.ERROR_MESSAGE);
				avatar_field.setText("");
			}
		}
		else
		{
			JOptionPane.showMessageDialog(null,"The selected file is not picture.",
					"Error",JOptionPane.ERROR_MESSAGE);
			avatar_field.setText("");
		}
	}
	
	/*
	 * Check all the inputs and show errors for those bad inputs
	 * Input: Nothing
	 * Output: Yes or No on good inputs
	 */
	private boolean valid_all()
	{
		String username=username_tf.getText().trim();
		String password=password_tf.getText().trim();
		String drivername=drivername_tf.getText().trim();
		String avatar_filename=avatar_field.getText();
		
		if(password.equals("") || username.equals("") || 
		drivername.equals("") || avatar_filename.equals(""))
		{
			JOptionPane.showMessageDialog(null,"One or more fields is empty!",
					"Error",JOptionPane.ERROR_MESSAGE);
			return false;
		}
		
		////////////////////////////////////
		//COBRA COMMUNICATION
		////////////////////////////////////
		//Pass username to GameServer and get result
		boolean available_username=true;
		
		if(!available_username)
		{
			JOptionPane.showMessageDialog(null,"Your username is taken. Please pick another.",
					"Error",JOptionPane.ERROR_MESSAGE);
			return false;
		}
			
		return true;
	}
	
	/*
	 * Create a new instance of Player and fill up with inputs
	 * Input: Nothing
	 * Output: Reference of the new instance of Player
	 */
	private Player create_new_account()
	{
		String username=username_tf.getText().trim();
		String password=password_tf.getText().trim();
		String drivername=drivername_tf.getText().trim();
		BufferedImage avatar;
		BufferedImage resized_avatar;
		long player_id;
		
		try
		{
			////////////////////////////////////
			//COBRA COMMUNICATION
			////////////////////////////////////
			//Get unique id from GameServer
			player_id=12345;//TEMP
			
			MessageDigest md = MessageDigest.getInstance("MD5");
			byte[] passwordBytes = password.getBytes("UTF-8");
			String md5_password = md.digest(passwordBytes).toString();
			
			avatar=ImageIO.read(new File(avatar_field.getText()));
			resized_avatar=resize(avatar, Configurations.avatar_length, Configurations.avatar_length);
			return new Player(player_id,drivername, username,md5_password, resized_avatar);
		}
		catch(Exception e)
		{
			JOptionPane.showMessageDialog(null,"The avatar picture is not readable.",
					"Error",JOptionPane.ERROR_MESSAGE);
			return null;
		}
	}
	
	/*
	 * Resize the picture to new picture with new dimensions
	 * Input: Reference of BufferedImage object, int new_width, int new_height
	 * Output: Reference of BufferedImage object
	 */
	private BufferedImage resize(BufferedImage this_mage, int new_width, int new_height)
	{
		int w = this_mage.getWidth();
		int h = this_mage.getHeight();
		BufferedImage resized_img = new BufferedImage(new_width, new_height, this_mage.getType());
		
		Graphics2D g = resized_img.createGraphics();
		g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
		g.drawImage(this_mage, 0, 0, new_width, new_height, 0, 0, w, h, null);
		g.dispose();
		
		return resized_img;
	}
}
